﻿// Copyright © 2011 Paul Vanukoff (pvanukoff@gmail.com)

using System;

namespace Bravura.Native.PluginBase.Oscillators
{
	/// <summary>
	/// A pseudo-oscillator which generates a kind of stepped noise.
	/// </summary>
	public class NoiseOscillator : Oscillator
	{
		#region Fields

		private Random _random = null;
		private double _time = 0.0;
		private double _lastVal = 0.0;
		private double _halfPeriod = 0.01;

		#endregion

		public NoiseOscillator(double dt, int? seed, double time) : base(dt)
		{
			_random = seed.HasValue ? new Random(seed.Value) : new Random();
			_time = time;
		}

		#region Methods

		/// <summary>
		/// Sets the frequency.
		/// </summary>
		public override void SetFrequency(double val)
		{
			_freqBase = val;
			updatePeriod();
		}

		/// <summary>
		/// Modulates the frequency.
		/// </summary>
		public override void ModulateFrequency(double val)
		{
			_freqMod = val;
			updatePeriod();
		}

		private void updatePeriod()
		{
			_halfPeriod = 0.5 / (_freqBase * _freqMod);
		}

		#endregion

		#region Implementation

		public override double Sample()
		{
			// calculate new sample ?
			while (_time >= _halfPeriod)
			{
				// wrap time
				_time = _time - _halfPeriod;

				// calculate new value
				_lastVal = 2.0 * _random.NextDouble() - 1.0;

				// apply distortion ?
				if (_applyDist && _time < _halfPeriod)
				{
					_lastVal = (_lastVal < 0.0) ? -Math.Pow(-_lastVal, _distortion) : Math.Pow(_lastVal, _distortion);
				}
			}

			// update time
			_time = _time + _dt;

			// return sample
			return _lastVal;
		}

		#endregion
	}
}
